﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using MySql.Data.MySqlClient;
using DateBaseConnectionPool;

namespace TestMySqlConnetPoll
{
    
    public class objDailyReport
    {
        public Int16 analog_no;
        public ObjValue MaxValue;
        public ObjValue MinValue;
        public ObjValue AvrValue;
        public Int32 MaxTime;
        public Int32 MinTime;
        public Int32 AvrTime;
        public Int16 bMaxValue; //原始值
        public Int16 bMinValue;
        public Int16 bAvrValue;
    }

    public struct objDailyReportValue
    {
        public ObjValue MaxValue;
        public ObjValue MinValue;
        public ObjValue AvrValue;
        public Int16 bMaxValue; //原始值
        public Int16 bMinValue;
        public Int16 bAvrValue;
        public Int32 MaxTime;
        public Int32 MinTime;
        public Int32 AvrTime;
        public string AttriName;
        public objSingleAnalogStruct objset;
    }
    /// <summary>
    /// 日报表，以设备做分类，每个设备中以模拟量类型，模拟量序号找到时间的模拟量值
    /// </summary>
    public class DailyReportTable
    {

        #region 外部函数定义 变量定义 日报表 
         
        public class objDailyReportMsgDev
        {
            public string DevName;      //设备名称
            public List<objDailyReportValue> DevValueList = new List<objDailyReportValue>();    //每行设备的值
        }

        public struct objMonthCurveValue
        {
            public int year;
            public int month;
            public int day;
            public objDailyReportValue Value;
        }

        public class objMonthCurve
        {
            public string AttriName;       //属性名称
            public objSingleAnalogStruct objset= new objSingleAnalogStruct();
            public List<objMonthCurveValue> MonthCurveValueList = new List<objMonthCurveValue>();    //某设备属性一个月的值
        }

        //不要时间列表，从专门的表格里取
        //public List<objDate> DailyReportTimeList = new List<objDate>();     //日报表时间列表
        //public List<objDate> MonthCurveTimeList = new List<objDate>();      //月曲线时间列表
        //public List<objDate> YearCurveTimeList = new List<objDate>();       //年曲线时间列表

        private int monthThreadSum = 0;
        private Mutex readMsum = new Mutex();
        private Mutex readYsum = new Mutex();
        private Mutex readDsum = new Mutex();
        private Mutex keyMutex = new Mutex();
        static private int keykey = 0;

        #region 日报表对外变量
        //public bool Ready_DailyReportTimeList = false;      //日报表的时间列表准备好
        public bool Ready_DailyReportValueList = false;     //日报表的值准备好
        private objDate DailyReportDate = new objDate();     //日报表的某一天
        //日报表，以MsgGather库的设备类型名称做键值，换天后，清除该缓冲区.
        public Dictionary<string, List<objDailyReportMsgDev>> DailyReportMsgDevValue = new Dictionary<string, List<objDailyReportMsgDev>>();
        public int DailyReportErrorFlag = 0;
        #endregion

        #region 月曲线对外变量
        private string MonthCruveMsgDevTypeName = "";        //月曲线的设备类型名称
        private objDate MonthCurveDate = new objDate();      //月曲线的某一月
        //月曲线值列表，以设备名称做键值，一次取出该设备所有属性的一个月的值
        public Dictionary<string, List<objMonthCurve>> MonthCurveValueList = new Dictionary<string, List<objMonthCurve>>();
        public bool Ready_MonthCurveValueList = false;
        public int MonthErrorFlag = 0;
        #endregion

        #region 年曲线对外变量
        public string YearCruveMsgDevTypeName = "";     //年曲线的设备类型名称
        public objDate YearCurveDate = new objDate();
        public Dictionary<string, List<objMonthCurve>> YearCurveValueList = new Dictionary<string, List<objMonthCurve>>();
        public int YearErrorFlag = 0;
        #endregion
               
        public bool Ready_YearCurveValueList = false;

        #region 内部组织数据用变量
        private int ReadAnalogTypeNum = 0;  //读取模拟量类型的数量，当该数目等于设备配置表的属性配置个数时，表示日报表读数据库完成。        
        public Dictionary<AnalogCodeType, List<objDailyReport>> DailyReportAnalogValueList = new Dictionary<AnalogCodeType, List<objDailyReport>>();
        public bool Ready_OneTypeDailyReportData = false; //一种模拟量日报表读取成功，终端调用时使用

        struct objMonthTypeDev
        {
            public AnalogCodeType AnalogType;
            public int AnalogNo;
        }
        private int ReadMonthCurveNum = 0;  //读取的月曲线模拟量个数
        private Dictionary<objMonthTypeDev, List<objMonthCurveValue>> MonthCurveAnalogValueList = new Dictionary<objMonthTypeDev, List<objMonthCurveValue>>();
        private int ReadYearCurveNum = 0;   //读取的年曲线模拟量个数
        private Dictionary<objMonthTypeDev, List<objMonthCurveValue>> YearCurveAnalogValueList = new Dictionary<objMonthTypeDev, List<objMonthCurveValue>>();
        #endregion

        public struct DailyReportThreadStruct
        {
            public string TableName;
            public CSM_DevType type;
            public objDate date;
            public AnalogCodeType AnalogType;
            public Int16 AnalogNo;
            public int  AnalogTypeNum;
            public string MsgDevTypeName;       //设备类型名称
            public string MsgDevName;           //设备名称
        }

        //public void ReadDailyReportTimeList()
        //{
        //    Ready_DailyReportTimeList = false;
        //    DailyReportThreadStruct obj = new DailyReportThreadStruct();
        //    obj.TableName = "DailyReport";            
        //    ThreadPool.QueueUserWorkItem(new WaitCallback(ThreadReadDailyReportTimeList), obj);
        //}

        /// <summary>
        /// 读设备的日报表，按照MsgGather关于设备的情况组织数据.
        /// </summary>
        /// <param name="date"></param>
        /// <param name="MsgDevName"></param>
        public void ReadDailyReportValueList(objDate date, string MsgDevTypeName)
        {
            Ready_DailyReportValueList = false;
            ReadAnalogTypeNum = 0;
            DailyReportErrorFlag = 0;
            DailyReportThreadStruct obj = new DailyReportThreadStruct();
            obj.TableName = "DailyReport";
            obj.date = date;
            if (date.day != DailyReportDate.day || date.month != DailyReportDate.month || date.year != DailyReportDate.year)
            {
                DailyReportDate = date;
                DailyReportMsgDevValue.Clear();
                DailyReportAnalogValueList.Clear();
            }
            if (DailyReportMsgDevValue.ContainsKey(MsgDevTypeName)) //已经在缓冲区中.
            {
                Ready_DailyReportValueList = true;
                return;
            }
            if (c_Device.DeviceMsgGather.ContainsKey(MsgDevTypeName))
            {
                int AnalogTypeNum = c_Device.DeviceMsgGather[MsgDevTypeName].ArrtiList.Count;   //模拟量类型个数
                List<AnalogCodeType> AnalogType = new List<AnalogCodeType>(); //模拟量类型列表
                for (int i = 0; i < AnalogTypeNum; i++)
                {
                    AnalogCodeType at = c_Device.DeviceMsgGather[MsgDevTypeName].ArrtiList[i].AnalogType;
                    if (at != AnalogCodeType.None)
                    {
                        if (AnalogType.Contains(at)) { }
                        else AnalogType.Add(at);
                    }
                }
                for (int i = 0; i < AnalogType.Count; i++)
                {
                    obj.TableName = "DailyReport";
                    obj.date = date;
                    obj.AnalogType = AnalogType[i];
                    ThreadPool.QueueUserWorkItem(new WaitCallback(ThreadReadDailyReportValueList), obj);
                    Thread.Sleep(30);
                }
                obj.AnalogTypeNum = AnalogType.Count;
                obj.MsgDevTypeName = MsgDevTypeName;
                ThreadPool.QueueUserWorkItem(new WaitCallback(ThreadOutPutDailyMsgDevList), obj);   //开启组织日报表数据线程.
            }
            else DailyReportErrorFlag = 1;  //设备类型无效，直接返回错误
        }
        /// <summary>
        /// 读设备的日报表，按照模拟量类型来读取,终端调用数据取使用这个函数
        /// </summary>
        /// <param name="date"></param>
        /// <param name="AnalogType"></param>
        public void ReadDailyReportValueList(objDate date, byte AnalogType)
        {
            Ready_OneTypeDailyReportData = false;
            DailyReportErrorFlag = 0;
            DailyReportThreadStruct obj = new DailyReportThreadStruct();
            obj.TableName = "DailyReport";
            obj.date = date;            
            obj.AnalogType = (AnalogCodeType)AnalogType;
            ThreadPool.QueueUserWorkItem(new WaitCallback(ThreadReadDailyReportValueList), obj);
        }

        private void ThreadOutPutDailyMsgDevList(object o)
        {
            DailyReportThreadStruct obj = (DailyReportThreadStruct)o;
            int MaxAnalogNum = obj.AnalogTypeNum;
            string MsgName = obj.MsgDevTypeName;    //设备类型名称
            DateTime sdt = DateTime.Now;
            while (true)
            {
                if (DailyReportErrorFlag != 0) break;
                if (MaxAnalogNum == ReadAnalogTypeNum)  //数据库已经全部读取完成
                {
                    if (c_Device.DeviceMsgGather.ContainsKey(MsgName))
                    {
                        List<objDailyReportMsgDev> TmpList = new List<objDailyReportMsgDev>();
                        int len = c_Device.DeviceMsgGather[MsgName].DevList.Count;
                        for (int i = 0; i < len; i++)
                        {
                            objDailyReportMsgDev TmpDailyReportMsgDev = new objDailyReportMsgDev();
                            TmpDailyReportMsgDev.DevName = c_Device.DeviceMsgGather[MsgName].DevList[i].DevName;    //赋值设备名
                            int attriLen = c_Device.DeviceMsgGather[MsgName].DevList[i].AnalogSet.Count;    //属性个数
                            for (int k = 0; k < attriLen; k++)
                            {
                                objDailyReportValue TmpReportValue = new objDailyReportValue();
                                AnalogCodeType AnalogType = c_Device.DeviceMsgGather[MsgName].ArrtiList[k].AnalogType;  //模拟量类型
                                string AnalogName = c_Device.DeviceMsgGather[MsgName].ArrtiList[k].AttriName;   //模拟量属性名称
                                objSingleAnalogStruct tmpObj = c_Device.GetSingleAnalogConfig(MsgName, TmpDailyReportMsgDev.DevName, AnalogName);
                                int tmpDevNo = c_Device.DeviceMsgGather[MsgName].DevList[i].AnalogSet[k];
                                if (tmpDevNo == -1) //表明没有这个值
                                {
                                    TmpReportValue.AvrValue = new ObjValue();
                                    TmpReportValue.MaxValue = new ObjValue();
                                    TmpReportValue.MinValue = new ObjValue();
                                    TmpReportValue.bAvrValue = -1;
                                    TmpReportValue.bMaxValue = -1;
                                    TmpReportValue.bMinValue = -1;
                                    TmpReportValue.AvrTime = 0;
                                    TmpReportValue.MaxTime = 0;
                                    TmpReportValue.MinTime = 0;
                                    TmpReportValue.objset = tmpObj;
                                    TmpReportValue.AttriName = AnalogName;
                                    TmpDailyReportMsgDev.DevValueList.Add(TmpReportValue);
                                }
                                else
                                {
                                    if (DailyReportAnalogValueList.Keys.Contains(AnalogType))
                                    {
                                        int devNum = DailyReportAnalogValueList[AnalogType].Count;
                                        for (int m = 0; m < devNum; m++)
                                        {
                                            if (DailyReportAnalogValueList[AnalogType][m].analog_no == tmpDevNo)
                                            {
                                                TmpReportValue.AvrValue = DailyReportAnalogValueList[AnalogType][m].AvrValue;
                                                TmpReportValue.AvrTime = DailyReportAnalogValueList[AnalogType][m].AvrTime;
                                                TmpReportValue.MaxTime = DailyReportAnalogValueList[AnalogType][m].MaxTime;
                                                TmpReportValue.MaxValue = DailyReportAnalogValueList[AnalogType][m].MaxValue;
                                                TmpReportValue.MinTime = DailyReportAnalogValueList[AnalogType][m].MinTime;
                                                TmpReportValue.MinValue = DailyReportAnalogValueList[AnalogType][m].MinValue;
                                                //---
                                                TmpReportValue.bAvrValue = DailyReportAnalogValueList[AnalogType][m].bAvrValue;
                                                TmpReportValue.bMaxValue = DailyReportAnalogValueList[AnalogType][m].bMaxValue;
                                                TmpReportValue.bMinValue = DailyReportAnalogValueList[AnalogType][m].bMinValue;
                                                TmpReportValue.AttriName = AnalogName;
                                                TmpReportValue.objset = tmpObj;
                                                TmpDailyReportMsgDev.DevValueList.Add(TmpReportValue);
                                                break;
                                            }
                                        }
                                    }
                                }
                            }
                            TmpList.Add(TmpDailyReportMsgDev);
                        }
                        DailyReportMsgDevValue.Add(MsgName, TmpList);       //加入到需要输出的列表
                        Ready_DailyReportValueList = true;
                        break;              //退出组织日报表线程.
                    }
                    DailyReportErrorFlag = 6;   //输出错误
                    break;      //错误退出
                }
                else
                {
                    if (DateTime.Now.Subtract(sdt).TotalSeconds >= 60)
                    {
                        DailyReportErrorFlag = 8;
                        break;
                    }
                    Thread.Sleep(500);
                }
            }
        }


        public void ReadMonthCurveValueList(objDate date, string MsgDevTypeName, string MsgDevName)
        {
            monthThreadSum = 0;
            MonthErrorFlag = 0;
            ReadMonthCurveNum = 0;
            Ready_MonthCurveValueList = false;
            DailyReportThreadStruct obj = new DailyReportThreadStruct();

            if (MonthCruveMsgDevTypeName != MsgDevTypeName)
            {
                MonthCruveMsgDevTypeName = MsgDevTypeName;
                MonthCurveAnalogValueList.Clear();
                MonthCurveValueList.Clear();
            }
            if (MonthCurveDate.year != date.year || MonthCurveDate.month != date.month)
            {
                MonthCurveDate.year = date.year;
                MonthCurveDate.month = date.month;
                MonthCurveAnalogValueList.Clear();
                MonthCurveValueList.Clear();
            }

            if (MonthCurveValueList.ContainsKey(MsgDevName) && MonthCurveDate.year == date.year && MonthCurveDate.month == date.month)
            {
                //该设备已经在缓冲区内，直接返回
                Ready_MonthCurveValueList = true;
                return;
            }
            
            if (c_Device.DeviceMsgGather.ContainsKey(MsgDevTypeName))
            {
                int tmpAttriNum = c_Device.DeviceMsgGather[MsgDevTypeName].ArrtiList.Count;     //设备属性个数

                int ValidAttriNum = 0;
                for (int i = 0; i < tmpAttriNum; i++)
                {
                    AnalogCodeType tmpType = c_Device.DeviceMsgGather[MsgDevTypeName].ArrtiList[i].AnalogType;
                    if (tmpType == AnalogCodeType.None) continue;   //开关量
                    int tmpDevNum = c_Device.DeviceMsgGather[MsgDevTypeName].DevList.Count;
                    for(int k =0;k<tmpDevNum;k++)
                    {
                        if(c_Device.DeviceMsgGather[MsgDevTypeName].DevList[k].DevName == MsgDevName)   //找到设备名称
                        {
                            int tmpNo = c_Device.DeviceMsgGather[MsgDevTypeName].DevList[k].AnalogSet[i];   //模拟量序号
                            if(tmpNo!=-1)    //设备无此属性，配置的为-1
                            {
                                ValidAttriNum++;
                                obj.TableName = "DailyReport";
                                obj.date = date;
                                obj.AnalogType = tmpType;
                                obj.AnalogNo = (Int16)tmpNo;
                                obj.MsgDevTypeName = MsgDevTypeName;
                                ThreadPool.QueueUserWorkItem(new WaitCallback(ThreadReadMonthCurveValueList), obj);
                                //Thread.Sleep(30);
                            }
                            break;  //一个模拟量值读取完毕，跳出
                        }
                    }
                }
                obj.AnalogTypeNum = ValidAttriNum;
                obj.MsgDevName = MsgDevName;
                obj.MsgDevTypeName = MsgDevTypeName;
                if (obj.AnalogTypeNum > 0)
                {
                    ThreadPool.QueueUserWorkItem(new WaitCallback(ThreadOutPutMonthCurveValueList), obj);
                }
                else MonthErrorFlag = 1;
            }
            else MonthErrorFlag = 1;
        }

        /// <summary>
        /// 组织月曲线线程，数据库读完成后，把读到的数据按照外部输出格式组织好。
        /// </summary>
        /// <param name="o"></param>
        private void ThreadOutPutMonthCurveValueList(object o)
        {
            DailyReportThreadStruct obj = (DailyReportThreadStruct)o;
            DateTime ndt = DateTime.Now;
            while (true)
            {                
                if (MonthErrorFlag != 0) break; //组织数据错误，退出                
                if (ReadMonthCurveNum == obj.AnalogTypeNum)     //这个设备所有的属性读取完毕
                {
                    string MsgDevName = obj.MsgDevName;
                    string MsgDevTypeName = obj.MsgDevTypeName;
                    if (c_Device.DeviceMsgGather.ContainsKey(MsgDevTypeName))
                    {
                        int devNum = c_Device.DeviceMsgGather[MsgDevTypeName].DevList.Count;
                        for (int i = 0; i < devNum; i++)
                        {
                            string TmpDevName = c_Device.DeviceMsgGather[MsgDevTypeName].DevList[i].DevName;
                            if (MsgDevName == TmpDevName)    //找到了设备名称
                            {
                                int len = c_Device.DeviceMsgGather[MsgDevTypeName].DevList[i].AnalogSet.Count;
                                for (int k = 0; k < len; k++)
                                {
                                    int tdo = c_Device.DeviceMsgGather[MsgDevTypeName].DevList[i].AnalogSet[k];     //模拟量序号
                                    AnalogCodeType tat = c_Device.DeviceMsgGather[MsgDevTypeName].ArrtiList[k].AnalogType;  //模拟量类型
                                    string tname = c_Device.DeviceMsgGather[MsgDevTypeName].ArrtiList[k].AttriName;
                                    objSingleAnalogStruct tmpObj = c_Device.GetSingleAnalogConfig(MsgDevTypeName, MsgDevName, tname);
                                    if (tdo != -1 && tat != AnalogCodeType.None)
                                    {
                                        objMonthCurve tmpMonthCurve = new objMonthCurve();
                                        tmpMonthCurve.AttriName = tname;
                                        objMonthTypeDev tmpobj = new objMonthTypeDev();
                                        tmpobj.AnalogType = tat;    //模拟量类型
                                        tmpobj.AnalogNo = tdo;      //模拟量序号                                        
                                        if (MonthCurveAnalogValueList.Keys.Contains(tmpobj))
                                        {
                                            tmpMonthCurve.objset = tmpObj;

                                            tmpMonthCurve.MonthCurveValueList = MonthCurveAnalogValueList[tmpobj]; //两List赋值.

                                            //for (int m = 0; m < MonthCurveAnalogValueList[tmpobj].Count; m++)
                                            //{
                                            //    tmpMonthCurve.MonthCurveValueList.Add(MonthCurveAnalogValueList[tmpobj][m]);    //两List赋值.
                                            //}
                                            if (MonthCurveValueList.ContainsKey(MsgDevName))
                                            {
                                                MonthCurveValueList[MsgDevName].Add(tmpMonthCurve);
                                            }
                                            else
                                            {
                                                List<objMonthCurve> t = new List<objMonthCurve>();
                                                t.Add(tmpMonthCurve);
                                                MonthCurveValueList.Add(MsgDevName, t);
                                            }
                                        }
                                    }
                                }
                                if(!MonthCurveValueList.ContainsKey(MsgDevName))
                                {
                                    List<objMonthCurve> t = new List<objMonthCurve>();
                                    MonthCurveValueList.Add(MsgDevName, t);
                                }
                                Ready_MonthCurveValueList = true;   //找到了设备
                                break;
                            }
                        }
                        break;
                    }
                    else
                    {
                        MonthErrorFlag = 6;
                        break;
                    }
                }
                else
                {
                    if (DateTime.Now.Subtract(ndt).TotalSeconds >= 60)
                    {
                        MonthErrorFlag = 8;
                        break;
                    }
                    Thread.Sleep(500);
                }
            }
        }


        public void ReadYearCurveValueList(objDate date, string MsgDevTypeName, string MsgDevName)
        {
            Ready_YearCurveValueList = false;
            ReadYearCurveNum = 0;
            DailyReportThreadStruct obj = new DailyReportThreadStruct();
            YearErrorFlag = 0;
            if (YearCruveMsgDevTypeName != MsgDevTypeName)
            {
                YearCruveMsgDevTypeName = MsgDevTypeName;
                YearCurveAnalogValueList.Clear();
                YearCurveValueList.Clear();
            }
            if (YearCurveDate.year != date.year)
            {
                YearCurveDate.year = date.year;
                YearCurveAnalogValueList.Clear();
                YearCurveAnalogValueList.Clear();
            }

            if (YearCurveValueList.ContainsKey(MsgDevName) && YearCurveDate.year == date.year)
            {
                //该设备已经在缓冲区内，直接返回
                Ready_YearCurveValueList = true;
                return;
            }

            if (c_Device.DeviceMsgGather.ContainsKey(MsgDevTypeName))
            {
                int tmpAttriNum = c_Device.DeviceMsgGather[MsgDevTypeName].ArrtiList.Count;     //设备属性个数

                int ValidAttriNum = 0;
                for (int i = 0; i < tmpAttriNum; i++)
                {
                    AnalogCodeType tmpType = c_Device.DeviceMsgGather[MsgDevTypeName].ArrtiList[i].AnalogType;
                    if (tmpType == AnalogCodeType.None) continue;   //开关量
                    int tmpDevNum = c_Device.DeviceMsgGather[MsgDevTypeName].DevList.Count;
                    for (int k = 0; k < tmpDevNum; k++)
                    {
                        if (c_Device.DeviceMsgGather[MsgDevTypeName].DevList[k].DevName == MsgDevName)
                        {
                            int tmpNo = c_Device.DeviceMsgGather[MsgDevTypeName].DevList[k].AnalogSet[i];   //模拟量序号
                            if (tmpNo != -1)    //模拟量类型和序号都正确，读取数据库内，该模拟量一年的数据
                            {
                                ValidAttriNum++;
                                obj.TableName = "DailyReport";
                                obj.date = date;
                                obj.AnalogType = tmpType;
                                obj.AnalogNo = (Int16)tmpNo;
                                obj.MsgDevTypeName = MsgDevTypeName;
                                ThreadPool.QueueUserWorkItem(new WaitCallback(ThreadReadYearCurveValueList), obj);
                                //Thread.Sleep(30);
                            }
                            break;
                        }
                    }
                }
                obj.AnalogTypeNum = ValidAttriNum;
                obj.MsgDevName = MsgDevName;
                obj.MsgDevTypeName = MsgDevTypeName;
                if (obj.AnalogTypeNum > 0)
                {
                    ThreadPool.QueueUserWorkItem(new WaitCallback(ThreadOutPutYearCurveValueList), obj);
                }
                else YearErrorFlag = 1;
            }
            else
            {
                YearErrorFlag = 1;
            }
        }

        private void ThreadOutPutYearCurveValueList(object o)
        {
            DailyReportThreadStruct obj = (DailyReportThreadStruct)o;
            DateTime ndt = DateTime.Now;
            while (true)
            {
                if (YearErrorFlag != 0) break;                
                if (ReadYearCurveNum == obj.AnalogTypeNum)     //这个设备所有的属性读取完毕
                {
                    string MsgDevName = obj.MsgDevName;
                    string MsgDevTypeName = obj.MsgDevTypeName;
                    if (c_Device.DeviceMsgGather.ContainsKey(MsgDevTypeName))
                    {
                        int devNum = c_Device.DeviceMsgGather[MsgDevTypeName].DevList.Count;
                        for (int i = 0; i < devNum; i++)
                        {
                            string TmpDevName = c_Device.DeviceMsgGather[MsgDevTypeName].DevList[i].DevName;
                            if (MsgDevName == TmpDevName)    //找到了设备名称
                            {
                                int len = c_Device.DeviceMsgGather[MsgDevTypeName].DevList[i].AnalogSet.Count;
                                for (int k = 0; k < len; k++)
                                {
                                    int tdo = c_Device.DeviceMsgGather[MsgDevTypeName].DevList[i].AnalogSet[k];     //模拟量序号
                                    AnalogCodeType tat = c_Device.DeviceMsgGather[MsgDevTypeName].ArrtiList[k].AnalogType;  //模拟量类型
                                    string tname = c_Device.DeviceMsgGather[MsgDevTypeName].ArrtiList[k].AttriName;
                                    objSingleAnalogStruct tmpObj = c_Device.GetSingleAnalogConfig(MsgDevTypeName, MsgDevName, tname);
                                    if (tdo != -1 && tat != AnalogCodeType.None)
                                    {
                                        objMonthCurve tmpYearCurve = new objMonthCurve();
                                        tmpYearCurve.AttriName = tname;
                                        objMonthTypeDev tmpobj = new objMonthTypeDev();
                                        tmpobj.AnalogType = tat;
                                        tmpobj.AnalogNo = tdo;
                                        if (YearCurveAnalogValueList.Keys.Contains(tmpobj))
                                        {
                                            tmpYearCurve.objset = tmpObj;
                                            tmpYearCurve.MonthCurveValueList = YearCurveAnalogValueList[tmpobj];
                                            //for (int m = 0; m < YearCurveAnalogValueList[tmpobj].Count; m++)
                                            //{
                                            //    tmpYearCurve.MonthCurveValueList.Add(YearCurveAnalogValueList[tmpobj][m]);    //两List赋值.
                                            //}
                                            if (YearCurveValueList.ContainsKey(MsgDevName))
                                            {
                                                YearCurveValueList[MsgDevName].Add(tmpYearCurve);
                                            }
                                            else
                                            {
                                                List<objMonthCurve> t = new List<objMonthCurve>();
                                                t.Add(tmpYearCurve);
                                                YearCurveValueList.Add(MsgDevName, t);
                                            }
                                        }
                                    }
                                }
                                Ready_YearCurveValueList = true;   //找到了设备
                                if(!YearCurveValueList.ContainsKey(MsgDevName))
                                {
                                    List<objMonthCurve> t = new List<objMonthCurve>();
                                    YearCurveValueList.Add(MsgDevName, t);
                                }
                                break;
                            }
                        }
                        break;
                    }
                    else
                    {
                        YearErrorFlag = 1;
                    }
                    break;
                }
                else
                {
                    if (DateTime.Now.Subtract(ndt).TotalSeconds >= 60)
                    {
                        YearErrorFlag = 8;
                        break;
                    }
                    Thread.Sleep(500);
                }
            }
        }

        #endregion

        #region 日报表
        /// <summary>
        /// 日报表更新数据，首先需要删除原来的设备，再进行插入操作
        /// </summary>
        /// <param name="TableName"></param>
        /// <param name="devtype"></param>
        /// <param name="dev_no"></param>
        /// <param name="obj"></param>
        /// <returns></returns>
        private bool InsertDailyReportData(string TableName,AnalogCodeType type, Int16 dev_no, objDate Nowdate, objDailyReport obj)
        {
            bool tmpFlag = false;
            if (TableName == "") return tmpFlag;
            if (MySql.c != null && MySql.c.State == PoolState.Run)
            {
                MySqlConnection con = new MySqlConnection();
                string key = TableName + DateTime.Now.Second.ToString() + DateTime.Now.Millisecond.ToString() + Interlocked.Increment(ref keykey).ToString();
                try
                {
                    con = (MySqlConnection)MySql.c.GetConnectionFormPool(key);
                }
                catch (MySqlException ex)
                {
                    //写异常日志
                    tmpFlag = false;
                }
                        
                if (con != null)
                {
                    //首先需删除原有的记录
                    StringBuilder dels = new StringBuilder();
                    dels.Append(string.Format("delete * from {0} where year = {1} and month = {2} and day = {3} ", TableName, Nowdate.year, Nowdate.month, Nowdate.day));
                    dels.Append(string.Format(" and  analog_type = {3} and analog_no = {4}", TableName, type, obj.analog_no));
                    MySqlCommand delcommand = new MySqlCommand(dels.ToString(), con);
                    delcommand.ExecuteNonQuery();

                    //再插入数据
                    StringBuilder InsertStatement = new StringBuilder();
                    InsertStatement.Append(string.Format("insert into {0}(year,month,analog_type,analog_no,MaxValue1,MinValue,AvrValue,MaxTime,MinTime,AvrTime", TableName));

                    InsertStatement.Append(")values(?year,?month,?analog_type,?analog_no,?MaxValue1,?MinValue,?AvrValue,?MaxTime,?MinTime,?AvrTime)");

                    MySqlCommand InsertCommand = new MySqlCommand(InsertStatement.ToString(), con);
                    InsertCommand.Parameters.Add(new MySqlParameter("?year", MySqlDbType.Int32)).Value = Nowdate.year;
                    InsertCommand.Parameters.Add(new MySqlParameter("?month", MySqlDbType.Byte)).Value = Nowdate.month;
                    InsertCommand.Parameters.Add(new MySqlParameter("?day", MySqlDbType.Byte)).Value = Nowdate.day;

                    InsertCommand.Parameters.Add(new MySqlParameter("?analog_type", MySqlDbType.Byte)).Value = (byte)type;
                    InsertCommand.Parameters.Add(new MySqlParameter("?analog_no", MySqlDbType.Int16)).Value = obj.analog_no;

                    InsertCommand.Parameters.Add(new MySqlParameter("?MaxValue1", MySqlDbType.Int16)).Value = obj.MaxValue;
                    InsertCommand.Parameters.Add(new MySqlParameter("?MinValue", MySqlDbType.Int16)).Value = obj.MinValue;
                    InsertCommand.Parameters.Add(new MySqlParameter("?AvrValue", MySqlDbType.Int16)).Value = obj.AvrValue;
                    InsertCommand.Parameters.Add(new MySqlParameter("?MaxTime", MySqlDbType.Int32)).Value = obj.MaxTime;
                    InsertCommand.Parameters.Add(new MySqlParameter("?MinTime", MySqlDbType.Int32)).Value = obj.MinTime;
                    InsertCommand.Parameters.Add(new MySqlParameter("?AvrTime", MySqlDbType.Int32)).Value = obj.AvrTime;

                    try
                    {
                        int k = InsertCommand.ExecuteNonQuery();
                        if (k == 1) tmpFlag = true;        //写入成功
                        else tmpFlag = false;              //写入失败
                    }
                    catch (MySqlException e)
                    {
                        //写异常日记
                        tmpFlag = false;       //写入失败
                    }
                    try
                    {
                        MySql.c.DisposeConnection(key);
                    }
                    catch (MySqlException e)
                    {
                        //写异常日记
                    }
                }
            }
            return tmpFlag;
        }

        /// <summary>
        /// 读取日报表时间列表，以设备类型读取，设备类型变更后，清除时间列表及缓冲区
        /// </summary>
        /// <param name="TableName"></param>
        /// <param name="type"></param>
        /// <returns></returns>
        //private void ThreadReadDailyReportTimeList(object o)
        //{
        //    DailyReportThreadStruct obj = (DailyReportThreadStruct)o;
        //    string TableName = obj.TableName;

        //    DailyReportTimeList.Clear();
        //    MonthCurveTimeList.Clear();
        //    YearCurveTimeList.Clear();

        //    if (TableName == "") return;
        //    if (MySql.c != null && MySql.c.State == PoolState.Run)
        //    {
        //        MySqlConnection con = new MySqlConnection();
        //        string key = TableName + DateTime.Now.Second.ToString() + DateTime.Now.Millisecond.ToString()+ (MySql.key++).ToString();
        //        try
        //        {
        //            con = (MySqlConnection)MySql.c.GetConnectionFormPool(key);
        //        }
        //        catch (MySqlException ex)
        //        {
        //            //写异常日志
        //        }
        //        if (con != null)
        //        {
        //            StringBuilder SelectStatement = new StringBuilder();

        //            SelectStatement.Append(string.Format("select(year,month,day) from{0}", TableName));         //没有按模拟量类型取，取出大量无用的数据.是否有好办法

        //            try
        //            {
        //                MySqlCommand selectCommand = new MySqlCommand(SelectStatement.ToString(), con);
        //                selectCommand.CommandTimeout = 120;   //120s操作超时

        //                MySqlDataReader read = selectCommand.ExecuteReader();
        //                while (read.Read())
        //                {
        //                    objDate t = new objDate();
        //                    t.year = read.GetInt32(read.GetOrdinal("year"));
        //                    t.month = read.GetByte(read.GetOrdinal("month"));
        //                    t.day = read.GetByte(read.GetOrdinal("day"));
        //                    if (DailyReportTimeList.Contains(t)) { }        //日报表时间列表
        //                    else DailyReportTimeList.Add(t);
        //                    t.day = 1;
        //                    if (MonthCurveTimeList.Contains(t)) { }         //月曲线时间列表
        //                    else MonthCurveTimeList.Add(t);
        //                    t.month = 1;
        //                    if (YearCurveTimeList.Contains(t)) { }          //年曲线时间列表
        //                    else YearCurveTimeList.Add(t);
        //                }
        //                read.Close();
        //                Ready_DailyReportTimeList = true;
        //            }
        //            catch (MySqlException e)
        //            {
        //                //写错误日志
        //            }
        //            try
        //            {
        //                MySql.c.DisposeConnection(key);
        //            }
        //            catch (MySqlException e)
        //            {
        //                //写错误日志
        //            }
        //        }
        //    }
        //}

        /// <summary>
        /// 日报表，只按照某个设备类型的某天来查询，一次取出某种设备类型的所有数据
        /// </summary>
        /// <param name="TableName"></param>
        /// <param name="date"></param>
        /// <param name="type"></param>
        /// <param name="ValidValueNum"></param>
        /// <returns></returns>
        private void ThreadReadDailyReportValueList(object o)
        {
            DailyReportThreadStruct obj = (DailyReportThreadStruct)o;
            string TableName = obj.TableName;
            objDate date = obj.date;
            AnalogCodeType type = obj.AnalogType;
            
            if (MySql.c != null && MySql.c.State == PoolState.Run)
            {
                MySqlConnection con = new MySqlConnection();
                string key = TableName + DateTime.Now.Second.ToString() + DateTime.Now.Millisecond.ToString() + Interlocked.Increment(ref keykey).ToString();
                try
                {
                    con = (MySqlConnection)MySql.c.GetConnectionFormPool(key);
                }
                catch (MySqlException ex)
                {
                    //写异常日志
                    DailyReportErrorFlag = 2;
                }
                        
                
                if (con != null)
                {
                    StringBuilder SelectStatement = new StringBuilder();

                    SelectStatement.Append("select analog_no,MaxValue1,MinValue,AvrValue,MaxTime,MinTime,AvrTime");

                    SelectStatement.Append(string.Format(" from {0} where year = {1} and month = {2} ", TableName, date.year, date.month));
                    SelectStatement.Append(string.Format(" and day = {0} and analog_type = {1}", date.day, (byte)type));
                    try
                    {
                        MySqlCommand selectCommand = new MySqlCommand(SelectStatement.ToString(), con);
                        selectCommand.CommandTimeout = 120;   //120s操作超时

                        MySqlDataReader read = selectCommand.ExecuteReader();
                        while (read.Read())
                        {
                            objDailyReport t = new objDailyReport();
                            t.analog_no = read.GetInt16(read.GetOrdinal("analog_no"));
                            Int16 tmpMax = read.GetInt16(read.GetOrdinal("MaxValue1"));
                            string AnalogName = c_Device.GetAnalogTypeName(type);
                            t.bMaxValue = tmpMax;
                            t.MaxValue = c_RealTimeValue.ConvertAnalogValue(AnalogName, tmpMax);
                            Int16 tmpMin = read.GetInt16(read.GetOrdinal("MinValue"));
                            t.bMinValue = tmpMin;
                            t.MinValue = c_RealTimeValue.ConvertAnalogValue(AnalogName, tmpMin);
                            Int16 tmpAvr = read.GetInt16(read.GetOrdinal("AvrValue"));
                            t.AvrValue = c_RealTimeValue.ConvertAnalogValue(AnalogName, tmpAvr);
                            t.bAvrValue = tmpAvr;

                            t.MaxTime = read.GetInt32(read.GetOrdinal("MaxTime"));
                            t.MinTime = read.GetInt32(read.GetOrdinal("MinTime"));
                            t.AvrTime = read.GetInt32(read.GetOrdinal("AvrTime"));
                            if (Monitor.TryEnter(DailyReportAnalogValueList, 500))
                            {
                                if (DailyReportAnalogValueList.Keys.Contains(type))
                                {
                                    DailyReportAnalogValueList[type].Add(t);
                                }
                                else
                                {
                                    List<objDailyReport> k = new List<objDailyReport>();
                                    k.Add(t);
                                    DailyReportAnalogValueList.Add(type, k);
                                }
                                Monitor.Exit(DailyReportAnalogValueList);
                            }
                            else
                            {
                                DailyReportErrorFlag = 11;
                                break;
                            }
                        }
                        read.Close();
                        Interlocked.Increment(ref ReadAnalogTypeNum);                    
                        Ready_OneTypeDailyReportData = true; //一种模拟量日报表读取成功，终端调用时使用
                    }
                    catch (MySqlException e)
                    {
                        DailyReportErrorFlag = 3;
                    }
                    try
                    {
                        MySql.c.DisposeConnection(key);
                    }
                    catch (MySqlException e)
                    {
                        DailyReportErrorFlag = 4;
                    }
                }
                else DailyReportErrorFlag = 6;
            }
            else DailyReportErrorFlag = 7;
        }

        private void ThreadReadMonthCurveValueList(object o)
        {
            DailyReportThreadStruct obj = (DailyReportThreadStruct)o;
            string TableName = obj.TableName;
            objDate date = obj.date;            
            AnalogCodeType AnalogType = obj.AnalogType;
            Int16 AnalogNo = obj.AnalogNo;
            string MsgDevTypeName = obj.MsgDevTypeName;
            
            if (MySql.c != null && MySql.c.State == PoolState.Run)
            {
                MySqlConnection con = new MySqlConnection();
                string key = TableName + DateTime.Now.Second.ToString() + DateTime.Now.Millisecond.ToString() + Interlocked.Increment(ref keykey).ToString();

                try
                {
                    con = (MySqlConnection)MySql.c.GetConnectionFormPool(key);
                }
                catch (MySqlException ex)
                {
                    //写异常日志
                    Console.WriteLine("月曲线出错");
                    MonthErrorFlag = 2;
                }
                        
                if (con != null)
                {
                    //取某种模拟量一个月的数据
                    StringBuilder SelectStatement = new StringBuilder();
                    SelectStatement.Append("select day,MaxValue1,MinValue,AvrValue,MaxTime,MinTime,AvrTime");
                    SelectStatement.Append(string.Format(" from {0} where year = {1} and month = {2} ", TableName, date.year, date.month));
                    SelectStatement.Append(string.Format(" and analog_type = {0} and analog_no = {1} ", (byte)AnalogType, AnalogNo));
                    try
                    {
                        MySqlCommand selectCommand = new MySqlCommand(SelectStatement.ToString(), con);
                        selectCommand.CommandTimeout = 120;   //120s操作超时

                        MySqlDataReader read = selectCommand.ExecuteReader();
                        while (read.Read())
                        {
                            objMonthCurveValue t = new objMonthCurveValue();
                            byte tmpDay = read.GetByte(read.GetOrdinal("day"));
                            t.year = date.year;
                            t.month = date.month;
                            t.day = tmpDay;
                            Int16 tmpMax = read.GetInt16(read.GetOrdinal("MaxValue1"));
                            string AnalogName = c_Device.GetAnalogTypeName(AnalogType);
                            t.Value.bMaxValue = tmpMax;
                            t.Value.MaxValue = c_RealTimeValue.ConvertAnalogValue(AnalogName, tmpMax);
                            Int16 tmpMin = read.GetInt16(read.GetOrdinal("MinValue"));
                            t.Value.MinValue = c_RealTimeValue.ConvertAnalogValue(AnalogName, tmpMin);
                            t.Value.bMinValue = tmpMin;
                            Int16 tmpAvr = read.GetInt16(read.GetOrdinal("AvrValue"));
                            t.Value.AvrValue = c_RealTimeValue.ConvertAnalogValue(AnalogName, tmpAvr);
                            t.Value.bAvrValue = tmpAvr;
                            t.Value.MaxTime = read.GetInt32(read.GetOrdinal("MaxTime"));
                            t.Value.MinTime = read.GetInt32(read.GetOrdinal("MinTime"));
                            t.Value.AvrTime = read.GetInt32(read.GetOrdinal("AvrTime"));

                            objMonthTypeDev tmp = new objMonthTypeDev();
                            tmp.AnalogType = AnalogType;
                            tmp.AnalogNo = AnalogNo;
                            if (Monitor.TryEnter(MonthCurveAnalogValueList,500))
                            {
                                if (MonthCurveAnalogValueList.Keys.Contains(tmp))
                                {
                                    MonthCurveAnalogValueList[tmp].Add(t);
                                }
                                else
                                {
                                    List<objMonthCurveValue> k = new List<objMonthCurveValue>();
                                    k.Add(t);
                                    MonthCurveAnalogValueList.Add(tmp, k);
                                }
                                Monitor.Exit(MonthCurveAnalogValueList);
                            }
                            else
                            {
                                MonthErrorFlag = 11;
                                break;
                            }
                        }
                        read.Close();
                        Interlocked.Increment(ref ReadMonthCurveNum);                        
                    }
                    catch (MySqlException e)
                    {
                        MonthErrorFlag = 3;
                        Console.WriteLine("月曲线出错");
                    }
                    try
                    {
                        MySql.c.DisposeConnection(key);
                    }
                    catch (MySqlException e)
                    {
                        MonthErrorFlag = 4;
                        Console.WriteLine("月曲线出错");
                    }
                }
                else MonthErrorFlag = 6;
            }
            else MonthErrorFlag = 7;
            monthThreadSum++;
            Console.WriteLine(string.Format("月曲线线程数:{0}，返回个数{1},err:{2}",monthThreadSum, ReadMonthCurveNum,MonthErrorFlag));
        }

        private void ThreadReadYearCurveValueList(object o)
        {
            DailyReportThreadStruct obj = (DailyReportThreadStruct)o;
            string TableName = obj.TableName;
            objDate date = obj.date;
            AnalogCodeType AnalogType = obj.AnalogType;
            Int16 AnalogNo = obj.AnalogNo;
            string MsgDevTypeName = obj.MsgDevTypeName;
            
            if (MySql.c != null && MySql.c.State == PoolState.Run)
            {
                MySqlConnection con = new MySqlConnection();
                string key = TableName + DateTime.Now.Second.ToString() + DateTime.Now.Millisecond.ToString() + Interlocked.Increment(ref keykey).ToString();
                try
                {
                    con = (MySqlConnection)MySql.c.GetConnectionFormPool(key);
                }
                catch (MySqlException ex)
                {
                    //写异常日志
                    YearErrorFlag = 1;
                }                        
                
                if (con != null)
                {
                    //取某种模拟量一个月的数据
                    StringBuilder SelectStatement = new StringBuilder();
                    SelectStatement.Append("select month,day,MaxValue1,MinValue,AvrValue,MaxTime,MinTime,AvrTime");
                    SelectStatement.Append(string.Format(" from {0} where year = {1}", TableName, date.year));
                    SelectStatement.Append(string.Format(" and analog_type = {0} and analog_no = {1} ", (byte)AnalogType, AnalogNo));
                    try
                    {
                        MySqlCommand selectCommand = new MySqlCommand(SelectStatement.ToString(), con);
                        selectCommand.CommandTimeout = 120;   //120s操作超时

                        MySqlDataReader read = selectCommand.ExecuteReader();
                        while (read.Read())
                        {
                            objMonthCurveValue t = new objMonthCurveValue();
                            byte tmpMonth = read.GetByte(read.GetOrdinal("month"));
                            byte tmpDay = read.GetByte(read.GetOrdinal("day"));
                            t.year = date.year;
                            t.month = tmpMonth;
                            t.day = tmpDay;
                            Int16 tmpMax = read.GetInt16(read.GetOrdinal("MaxValue1"));
                            string AnalogName = c_Device.GetAnalogTypeName(AnalogType);
                            t.Value.MaxValue = c_RealTimeValue.ConvertAnalogValue(AnalogName, tmpMax);
                            t.Value.bMaxValue = tmpMax;
                            Int16 tmpMin = read.GetInt16(read.GetOrdinal("MinValue"));
                            t.Value.MinValue = c_RealTimeValue.ConvertAnalogValue(AnalogName, tmpMin);
                            t.Value.bMinValue = tmpMin;
                            Int16 tmpAvr = read.GetInt16(read.GetOrdinal("AvrValue"));
                            t.Value.AvrValue = c_RealTimeValue.ConvertAnalogValue(AnalogName, tmpAvr);
                            t.Value.bAvrValue = tmpAvr;
                            t.Value.MaxTime = read.GetInt32(read.GetOrdinal("MaxTime"));
                            t.Value.MinTime = read.GetInt32(read.GetOrdinal("MinTime"));
                            t.Value.AvrTime = read.GetInt32(read.GetOrdinal("AvrTime"));

                            objMonthTypeDev tmp = new objMonthTypeDev();
                            tmp.AnalogType = AnalogType;
                            tmp.AnalogNo = AnalogNo;
                            if (Monitor.TryEnter(YearCurveAnalogValueList, 500))
                            {
                                if (YearCurveAnalogValueList.Keys.Contains(tmp))
                                {
                                    YearCurveAnalogValueList[tmp].Add(t);
                                }
                                else
                                {
                                    List<objMonthCurveValue> k = new List<objMonthCurveValue>();
                                    k.Add(t);
                                    YearCurveAnalogValueList.Add(tmp, k);
                                }
                                Monitor.Exit(YearCurveAnalogValueList);
                            }
                            else
                            {
                                YearErrorFlag = 11;
                                break;
                            }
                        }
                        read.Close();
                        Interlocked.Increment(ref ReadYearCurveNum);                        
                    }
                    catch (MySqlException e)
                    {
                        YearErrorFlag = 2;
                    }
                    try
                    {
                        MySql.c.DisposeConnection(key);
                    }
                    catch (MySqlException e)
                    {
                        YearErrorFlag = 3;
                    }
                }
                else YearErrorFlag = 6;
            }
            else YearErrorFlag = 7;
        }
        #endregion
    }
}
